package my.web;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import my.dto.Result;
import my.org.json.JSONArray;
import my.org.json.JSONObject;

/**
 * Web工具类
 * @author 夏冬琦
 *
 */
public class MyWeb {
	

	private MyWeb() {}
	

	/**
	 * 向浏览器输出纯文本字符串
	 * @param response
	 * @param text
	 * @throws IOException
	 */
	public static void printText(HttpServletResponse response,String text) throws IOException {
		
		response.setContentType("text/plain;charset=UTF-8");
		PrintWriter out =response.getWriter();
		
		out.print(text);
		
		out.flush();
		out.close();
		
	}
	
	/**
	 * 向浏览器输出html字符串
	 * @param response
	 * @param text
	 * @throws IOException
	 */
	public static void printHtml(HttpServletResponse response,String html) throws IOException {
		
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out =response.getWriter();
		
		out.print(html);
		
		out.flush();
		out.close();
		
	}
	
	/**
	 * 向浏览器输出Json字符串
	 * @param response
	 * @param jsonString
	 * @throws IOException
	 */
	public static void printJson(HttpServletResponse response,String jsonString) throws IOException {
		
		response.setContentType("application/json;charset=UTF-8");
		PrintWriter out =response.getWriter();
		
		out.print(jsonString);
		
		out.flush();
		out.close();
		
	}
	
	/**
	 * 将Result(结果)对象转化为Json字符串向浏览器输出
	 * @param response 
	 * @param result 结果对象
	 * @throws IOException
	 */
	public static void printJson(HttpServletResponse response,Result result) throws IOException {
		
		response.setContentType("application/json;charset=UTF-8");
		PrintWriter out =response.getWriter();
		
		out.print(new JSONObject(result));
		
		out.flush();
		out.close();
		
	}
	
	/**
	 * 将JavaBean对象转化为Json字符串向浏览器输出
	 * @param response 
	 * @param bean JavaBean对象
	 * @throws IOException
	 */
	public static void printJson(HttpServletResponse response,Object bean) throws IOException {
		
		response.setContentType("application/json;charset=UTF-8");
		PrintWriter out =response.getWriter();
		
		out.print(new JSONObject(bean));
		
		out.flush();
		out.close();
		
	}
	
	/**
	 * 将Map集合对象转化为Json字符串向浏览器输出
	 * @param response 
	 * @param map Map集合
	 * @throws IOException
	 */
	public static void printJson(HttpServletResponse response,Map<String,Object> map) throws IOException {
		
		response.setContentType("application/json;charset=UTF-8");
		PrintWriter out =response.getWriter();
		
		out.print(new JSONObject(map));
		
		out.flush();
		out.close();
		
	}
	
	/**
	 * 将Collection集合对象转化为Json字符串向浏览器输出
	 * @param response 
	 * @param collection Collection集合
	 * @throws IOException
	 */
	public static void printJson(HttpServletResponse response,Collection<?> collection) throws IOException {
		
		response.setContentType("application/json;charset=UTF-8");
		PrintWriter out =response.getWriter();
		
		out.print(new JSONArray(collection));
		
		out.flush();
		out.close();
		
	}
	
	/**
	 * 将浏览器的请求的参数封装为JavaBean对象
	 * @param beanClass 封装参数的JavaBean的类型
	 * @param request 请求对象
	 * @return 返回封装了浏览器的请求的参数的JavaBean对象
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static <T> T getBeanFromRequest(Class<T> beanClass,HttpServletRequest request) {
		
		
		T bean=null;
		try {
			bean = beanClass.newInstance();
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
		
		
		Method[] mds = beanClass.getMethods();
		
		for(Method md : mds) {
			
			String mdName = md.getName();			
			
			if(mdName.startsWith("set") &&
					mdName.length() > 3 &&
					md.getParameterCount() == 1 ) {
				
				//获取set方法对应属性名称
				StringBuilder fdName = 
						new StringBuilder(String.valueOf(Character.toLowerCase(mdName.charAt(3))));
				
				
				if(mdName.length()>4)fdName.append(mdName.substring(4));
				
				String[] values = request.getParameterValues(fdName.toString());
				
				if(values==null || values.length==0) {
					continue;
				}
				
				Class<?> argType = md.getParameterTypes()[0];
				
				
				execSetMethod(argType, md, bean, values);
				
				
			}
		}
		
		return bean;
		
		
		
		
	}
	
	private static final Map<String,SimpleDateFormat> FMT_MAP ;
	
	static {
		FMT_MAP = new HashMap<String,SimpleDateFormat>();
		
		FMT_MAP.put("^(19|20)[0-9]{2}-(11|12|0[1-9])-(0[1-9]|[1-2][0-9]|3[0-1])$", new SimpleDateFormat("yyyy-MM-dd"));
		
		FMT_MAP.put("^(19|20)[0-9]{2}-(11|12|0[1-9])-(0[1-9]|[1-2][0-9]|3[0-1]) ([0,1][0-9]|2[0-3]):[0-5][0-9]$", new SimpleDateFormat("yyyy-MM-dd HH:mm"));
		FMT_MAP.put("^(19|20)[0-9]{2}-(11|12|0[1-9])-(0[1-9]|[1-2][0-9]|3[0-1])T([0,1][0-9]|2[0-3]):[0-5][0-9]$", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm"));
		
		FMT_MAP.put("^(19|20)[0-9]{2}-(11|12|0[1-9])-(0[1-9]|[1-2][0-9]|3[0-1]) ([0,1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
		FMT_MAP.put("^(19|20)[0-9]{2}-(11|12|0[1-9])-(0[1-9]|[1-2][0-9]|3[0-1]) ([0,1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9].([0-9]|[1-9][0-9]{1,2})$", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S"));
		FMT_MAP.put("^(19|20)[0-9]{2}-(11|12|0[1-9])-(0[1-9]|[1-2][0-9]|3[0-1]) ([0,1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9].[0-9]{1,3}$", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
	
	}
	
	private static SimpleDateFormat getDateFMT(String value) throws Exception {
		Set<String> keys = FMT_MAP.keySet();
		for(String key : keys) {
			if(Pattern.matches(key, value)) {
				return FMT_MAP.get(key);
			}
		}
		throw new Exception("字符串："+value+" 无法被转化为日期！");
	}
	
		
	private static void execSetMethod(Class<?> argType , Method md , Object bean , String[] values ) {
		
		try {
			if (argType == String[].class) {
				md.invoke(bean, values);
			}

			else if (argType == String.class) {
				md.invoke(bean, values[0]);
			}

			else if (argType == Integer[].class) {
				Integer[] arr = new Integer[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Integer.parseInt(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == int[].class) {
				int[] arr = new int[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Integer.parseInt(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == Integer.class || argType == int.class) {
				md.invoke(bean, Integer.parseInt(values[0]));
			}

			else if (argType == Long[].class) {
				Long[] arr = new Long[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Long.parseLong(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == long[].class) {
				long[] arr = new long[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Long.parseLong(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == Long.class || argType == long.class) {
				md.invoke(bean, Long.parseLong(values[0]));
			}

			else if (argType == Float[].class) {
				Float[] arr = new Float[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Float.parseFloat(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == float[].class) {
				float[] arr = new float[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Float.parseFloat(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == Float.class || argType == float.class) {
				md.invoke(bean, Float.parseFloat(values[0]));
			}

			else if (argType == Double[].class) {
				Double[] arr = new Double[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Double.parseDouble(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == double[].class) {
				double[] arr = new double[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Double.parseDouble(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == Double.class || argType == double.class) {
				md.invoke(bean, Double.parseDouble(values[0]));
			}

			else if (argType == Boolean[].class) {
				Boolean[] arr = new Boolean[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Boolean.parseBoolean(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == boolean[].class) {
				boolean[] arr = new boolean[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = Boolean.parseBoolean(values[i]);
				}
				md.invoke(bean, arr);
			} else if (argType == Boolean.class || argType == boolean.class) {
				md.invoke(bean, Boolean.parseBoolean(values[0]));
			}

			else if (argType == Date[].class) {
				Date[] arr = new Date[values.length];
				for (int i = 0; i < arr.length; i++) {
					arr[i] = getDateFMT(values[i]).parse(values[i]);
				}
				md.invoke(bean, arr);
			}

			else if (argType == Date.class) {
				md.invoke(bean, getDateFMT(values[0]).parse(values[0]));
			} 
		} catch (Exception e) {
			System.out.println("警告：以下异常信息可以忽略！");
			System.out.println(e);
			System.out.println("警告：以上异常信息可以忽略！");
		}
		
	}
	

}
